package edu.gmu.projects.fireresponder.missionplanner;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import edu.gmu.projects.fireresponder.environment.Asset;
import edu.gmu.projects.fireresponder.environment.Building;
import edu.gmu.projects.fireresponder.environment.Path;
import edu.gmu.projects.fireresponder.environment.Route;
import edu.gmu.projects.fireresponder.environment.Safespot;
import edu.gmu.projects.fireresponder.plan.PlanObjective;
import edu.gmu.projects.fireresponder.plan.PlanObjectives;

public class MissionPlan implements Iterable<PlanObjective> {

	private PlanObjectives objectives;

	protected MissionPlan() {
	}
	
	public MissionPlan(final InputStream stream) {
		ObjectMapper mapper = new ObjectMapper();

		try {
			objectives = mapper.readValue(stream, PlanObjectives.class);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public List<PlanObjective> getPlanObjectives() {
		return objectives.getObjectives();
	}

	public Iterator<PlanObjective> iterator() {
		return objectives.iterator();
	}

	// returns true if the new plan matches the tail of the old plan, and any buildings missing
	// in the new plan that exist in the head of the old plan have been completed.  This represents
	// a plan that has been in progress, partially completed, but the remaining is still the same
	public static boolean planChanged(Map<String, Asset> oldPlan, Map<String, Asset> newPlan) {
		List<Asset> newPlanList = new LinkedList<Asset>();
		newPlanList.addAll(newPlan.values());
		Collections.reverse(newPlanList);

		List<Asset> oldPlanList = new LinkedList<Asset>();
		oldPlanList.addAll(oldPlan.values());
		Collections.reverse(oldPlanList);
		
		for(int i = 0; i < oldPlanList.size(); i++) {
			if(newPlanList.size() <= i) {  // new plan list doesn't include these initial steps (or trail steps in reverse order)
				if(oldPlanList.get(i) instanceof Building && ! ((Building)oldPlanList.get(i)).isCleared()) {
					return true;
				}
			} else {
				if(! oldPlanList.get(i).getId().equals(newPlanList.get(i).getId())) {
					return true;
				}
					
			}
		}
		return false;
	}
	
	public static String buildString(Map<String, Asset> mission) {
		StringBuilder sb = new StringBuilder();
		sb.append("{\"objectives\": [");

		boolean first = true;
		for(Asset asset : mission.values()) {
			if(!first) {
				sb.append(",");
			} else {
				first = false;
			}
			sb.append("{");
			if(asset instanceof Route) {
				sb.append("\"@class\":\"edu.gmu.projects.fireresponder.plan.PlanRoute\",");
				sb.append("\"route\":[");
				boolean firstPath = true;
				for(Path p : ((Route) asset).getPaths()) {
					if(!firstPath) {
						sb.append(",");
					} else {
						firstPath = false;
					}
					sb.append("{");
					sb.append("\"@class\":\"edu.gmu.projects.fireresponder.plan.PlanPath\",");
					sb.append("\"path\":\"").append(p.getId()).append("\"");
					sb.append("}");
				}
				sb.append("]");
			} else if (asset instanceof Building) {
				sb.append("\"@class\":\"edu.gmu.projects.fireresponder.plan.PlanBuilding\",");
				sb.append("\"building\":\"").append(asset.getId()).append("\""); 				
			} else if (asset instanceof Safespot) {
				sb.append("\"@class\":\"edu.gmu.projects.fireresponder.plan.PlanSafespot\",");
				sb.append("\"safespot\":\"").append(asset.getId()).append("\""); 

			}
			sb.append("}");
		}

		sb.append("]}");

		return sb.toString();
	}
}